﻿//
// Created by Administrator on 2022/6/16.
//

#include "rapidjson/document.h"
#include "rapidjson/prettywriter.h"
#include "rapidjson/stringbuffer.h"
#include "MyDialog.h"
#include "action_event.h"
#include "ids.h"
#include "WorkThread.h"
#include "NotificationIcon.h"
#include "HostInfoPanel.h"
#include <utils.h>
#include "public/tag.h"
#include "repDialog.h"

using namespace rapidjson;

#define TIMER_ID 1000

extern bool loopIt;
extern bool backup;
BEGIN_EVENT_TABLE ( MyDialog, wxFrame )
                EVT_MENU ( ACTION_EVENT, MyDialog::OnActionEvent )
                EVT_MENU ( ID_EXIT, MyDialog::OnExit )
                EVT_MENU ( ID_MENU_OPTION, MyDialog::OnOption )
                EVT_MENU ( ID_DIALOG_REPOSITORY, MyDialog::OnOpenRepository )
                EVT_TIMER( TIMER_ID, MyDialog::OnTimer )
                EVT_CLOSE(MyDialog::OnClose )
END_EVENT_TABLE()

/*
 * post:
 *  what I post
 * get:
 *  what I want to get
 * post my host info
 * get other hosts info
 * post my host info
 * get all info that post to me
 */
void MyDialog::BuildMainView() {
    this->SetSizeHints( wxDefaultSize, wxDefaultSize );

    wxBoxSizer* bSizer1;
    bSizer1 = new wxBoxSizer( wxVERTICAL );

    wxStaticBoxSizer* sbSizer3;
    sbSizer3 = new wxStaticBoxSizer(
            new wxStaticBox( this, wxID_ANY,
                    wxT("TOUCH") ), wxHORIZONTAL );

    bitmap_running = new wxStaticBitmap( sbSizer3->GetStaticBox(),
            wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 );
    sbSizer3->Add( bitmap_running, 0, wxALL, 5 );

    static_response_time = new wxStaticText( sbSizer3->GetStaticBox(),
            wxID_ANY, wxT("MyLabel"), wxDefaultPosition, wxDefaultSize, 0 );
    static_response_time->Wrap( -1 );
    sbSizer3->Add( static_response_time, 0, wxALL, 5 );

    m_checkBox_backup = new wxCheckBox(sbSizer3->GetStaticBox(), wxID_ANY,
                                       wxT("保存报文"), wxDefaultPosition, wxDefaultSize, 0 );
    m_checkBox_backup->SetToolTip(wxT("服务端保存报文至数据库") );

    sbSizer3->Add(m_checkBox_backup, 0, wxALL, 5 );

    //
    /*
    m_checkBox_thread_pause = new wxCheckBox(sbSizer3->GetStaticBox(), wxID_ANY,
                                       wxT("暂停工作线程"), wxDefaultPosition, wxDefaultSize, 0 );
    m_checkBox_thread_pause->SetToolTip(wxT("运行/暂停") );

    sbSizer3->Add( m_checkBox_thread_pause, 0, wxALL, 5 );
*/
    //获得输入的wxMessageBox
    //然后写入delay

    bSizer1->Add( sbSizer3, 0, wxEXPAND, 5 );

    clients_static_box_sizer = new wxStaticBoxSizer( new wxStaticBox( this,
            wxID_ANY, wxT("CLIENTS") ), wxVERTICAL );

    scrolled_clients_window = new wxScrolledWindow(clients_static_box_sizer->GetStaticBox(),
                                                   wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxVSCROLL );
    scrolled_clients_window->SetScrollRate(5, 5 );

    scroll_window_sizer = new wxBoxSizer(wxVERTICAL );

    scrolled_clients_window->SetSizer( scroll_window_sizer );
    scrolled_clients_window->Layout();
    scroll_window_sizer->Fit( scrolled_clients_window );
    clients_static_box_sizer->Add(scrolled_clients_window, 1, wxEXPAND | wxALL, 0 );

    bSizer1->Add( clients_static_box_sizer, 1, wxEXPAND, 0 );

    //server static
    auto * serverStatusSizer = new wxBoxSizer( wxHORIZONTAL );
    static_pid_datetime = new wxStaticText( this,
                                            wxID_ANY, wxT("MyLabel"), wxDefaultPosition, wxDefaultSize, 0 );
    static_pid_datetime->SetMinSize( wxSize( 75,-1 ) );
    serverStatusSizer->Add( static_pid_datetime, 0, wxEXPAND | wxALL, 0 );

    static_pid = new wxStaticText( this,
                                   wxID_ANY, wxT("MyLabel"), wxDefaultPosition, wxDefaultSize, 0 );
    static_pid->SetMinSize( wxSize( 75,-1 ) );
    serverStatusSizer->Add( static_pid, 0, wxEXPAND | wxALL, 0 );
    static_cpu = new wxStaticText(this,
                                  wxID_ANY, wxT("MyLabel"), wxDefaultPosition, wxDefaultSize, 0 );
    static_cpu->SetMinSize( wxSize( 150,-1 ) );
    serverStatusSizer->Add( static_cpu, 0, wxEXPAND | wxALL, 0 );
    static_proc_mem = new wxStaticText(this,
                                       wxID_ANY, wxT("MyLabel"), wxDefaultPosition, wxDefaultSize, 0 );
    static_proc_mem->SetMinSize( wxSize( 75,-1 ) );
    serverStatusSizer->Add( static_proc_mem, 0, wxEXPAND | wxALL, 0 );
    static_proc_virtual_mem = new wxStaticText(this,
                                               wxID_ANY, wxT("MyLabel"), wxDefaultPosition, wxDefaultSize, 0 );
    static_proc_virtual_mem->SetMinSize( wxSize( 75,-1 ) );
    serverStatusSizer->Add( static_proc_virtual_mem, 0, wxEXPAND | wxALL, 0 );
    bSizer1->Add( serverStatusSizer, 0, wxALL, 0 );
    this->SetSizer( bSizer1 );
    this->Layout();
    m_statusBar1 = this->CreateStatusBar( 1, wxSTB_SIZEGRIP, wxID_ANY );

    this->Centre( wxBOTH );
}

void MyDialog::BuildMenu() {
    m_menubar1 = new wxMenuBar( 0 );
    m_menu1 = new wxMenu();
    wxMenuItem* m_menuItem1;
    m_menuItem1 = new wxMenuItem( m_menu1, ID_MENU_OPTION,
                                  wxString( wxT("配置") ) ,
                                  wxEmptyString, wxITEM_NORMAL );
    m_menu1->Append( m_menuItem1 );

    wxMenuItem* m_menuItem2;
    m_menuItem2 = new wxMenuItem( m_menu1, ID_DIALOG_REPOSITORY,
                                  wxString( wxT("入库") ) ,
                                  wxEmptyString, wxITEM_NORMAL );
    m_menu1->Append( m_menuItem2 );

    m_menu1->AppendSeparator();

    wxMenuItem* m_menuExit;
    m_menuExit = new wxMenuItem(m_menu1, ID_EXIT,
                                wxString( wxT("Exit") ) ,
                                wxEmptyString, wxITEM_NORMAL );
    m_menu1->Append( m_menuExit );

    m_menubar1->Append( m_menu1, wxT("FILE") );

    this->SetMenuBar( m_menubar1 );
}

/*
 * static text
 *  last response time
 *  本机回执信息
 * menu:
 *  show all info
 *  new dialog
 * my response:
 * all client info
 */
MyDialog::MyDialog( wxWindow *parent )
    :wxFrame ( parent, ID_FRAME_REPOSITORY, "Transfer", wxDefaultPosition, wxDefaultSize,
                       wxDEFAULT_FRAME_STYLE ^ wxMAXIMIZE_BOX ^ wxRESIZE_BORDER )
{
    SetLabel("Transfer");
    wxIcon icon(wxT("logo" ));
    SetIcon( icon );
    SetClientSize ( wxSize ( 550, 600 ) );
     /*
    auto* dialogRootBoxSizer = new wxBoxSizer ( wxVERTICAL );
    responseTime = new wxStaticText ( this,
            wxID_ANY, "等待回执" );
    dialogRootBoxSizer->Add( responseTime );
    this->SetSizer ( dialogRootBoxSizer );*/
    BuildMenu();
    BuildMainView();
    //start the thread
    //dialog不显示不更新listView
    mThread = new WorkThread( this );
    mThread->Run();
    notification = new NotificationIcon( this );
    m_checkBox_backup->Connect(wxEVT_LEFT_DOWN,
                               wxMouseEventHandler(MyDialog::OnBackupLineClick), nullptr, this);
}

MyDialog::~MyDialog(){
    mThread->Delete();
    m_checkBox_backup->Disconnect(wxEVT_LEFT_DOWN,
                                  wxMouseEventHandler(MyDialog::OnBackupLineClick), nullptr, this);
}

void MyDialog::BuildHostItemView( GetHostInfo* hostInfo ) {
    scroll_window_sizer->Add( new HostInfoPanel( this, scrolled_clients_window, hostInfo ) );
    //scrolled_clients_window->SetSizer( scroll_window_sizer );
    scrolled_clients_window->Layout();
    scroll_window_sizer->Fit( scrolled_clients_window );
}

void MyDialog::OnActionEvent( wxCommandEvent &event ){
    const int token = event.GetInt();
    const long liType = event.GetExtraLong();
    char datetime[256];
    switch ( token ) {
        case TOKEN_UDP_MESSAGE_RESPONSE:{
            GetNowTime( datetime );
            static_response_time->SetLabel( datetime );
            auto* recv_buf = ( const char* )event.GetClientData();
            rapidjson::Document doc;
            bool r = doc.Parse( recv_buf ).HasParseError();
            if( !r ){
                if( doc.HasMember( key_resp_key_get ) && doc[key_resp_key_get].IsObject() ) {
                    if ( doc[key_resp_key_get].HasMember("hosts")
                                && doc[key_resp_key_get][key_resp_hosts_info].IsArray()) {
                        Value &hostsNode = doc[key_resp_key_get]["hosts"];
                        int d = hostsNode.Size();
                        scrolled_clients_window->DestroyChildren();
                        wxVector< std::shared_ptr<GetHostInfo> > tmp;
                        infos.swap( tmp );
                        for( rapidjson::SizeType i=0; i< hostsNode.Size(); i++ ) {
                            shared_ptr<GetHostInfo> hostInfo( new GetHostInfo( hostsNode[i][ key_resp_hosts_datetime ].GetString(),
                                                 hostsNode[i][ key_resp_hosts_hostname ].GetString(),
                                                 hostsNode[i][ key_resp_hosts_wan_ip ].GetString(),
                                                 hostsNode[i][ key_resp_hosts_system ].GetString(),
                                                 hostsNode[i][ key_resp_hosts_client_install_dir ].GetString(),
                                                 hostsNode[i][ key_resp_hosts_interfaces ].GetString()));
                            infos.push_back( hostInfo );
                            BuildHostItemView( hostInfo.get() );
                        }
                    }else if ( doc[key_resp_key_get].HasMember(key_resp_get_tag )
                            && doc[key_resp_key_get][key_resp_get_tag].IsString()  ){
                        if( strcmp( doc[key_resp_key_get][key_resp_get_tag].GetString(), key_resp_server_status )==0 ) {
                            if( doc.HasMember("datetime") )
                                static_pid_datetime->SetLabel(
                                    wxString::Format( "%s", doc["datetime"].GetString()));
                            static_pid->SetLabel(
                                    wxString::Format( "pid: %d",
                                            doc[key_resp_key_get][key_resp_server_status_pid].GetInt()));
                            static_cpu->SetLabel(
                                    wxString::Format( "cpu: %f",
                                            doc[key_resp_key_get][key_resp_server_status_cpu].GetFloat()));
                            static_proc_mem->SetLabel(
                                    wxString::Format( "mem: %d",
                                            doc[key_resp_key_get][key_resp_server_status_mem].GetInt()));
                            static_proc_virtual_mem->SetLabel(
                                    wxString::Format( "v_mem: %d",
                                            doc[key_resp_key_get][key_resp_server_status_virtual_mem].GetInt()));
                        }
                    }
                }
            }
            break;
        }
        case TOKEN_UDP_LOOP_END:{
            //之前的线程已退出，可以重起新线程
            break;
        }
    }
}

void MyDialog::OnTimer(wxTimerEvent &event) {

}

void MyDialog::OnClose(wxCloseEvent& event){
    /*
    mThread->Pause();
    mThread->Kill();

    if(event.CanVeto()){
        event.Veto();
    }*/
    //wxFrame::Close();
    //Destroy();
    Show(false);
}

void MyDialog::OnExit( wxCommandEvent &event ){
    if ( wxMessageBox(wxT("确定要退出吗"), wxT("请确认"),
                      wxICON_QUESTION | wxYES_NO ) == wxYES ){
        notification->RemoveIcon();
        ExitProcess( 0 );
    }
}

void MyDialog::OnBackupLineClick(wxMouseEvent &event) {
    backup = this->m_checkBox_backup->GetValue();
}

//暂停不了，不如重启
void MyDialog::OnWorkThreadPause(wxMouseEvent &event) {
    if( this->m_checkBox_thread_pause->GetValue() ){
        if( !mThread->IsPaused() ) {
            mThread->Pause();
            m_checkBox_thread_pause->SetBackgroundColour( wxColour( 255, 0, 0 ));
        }
    }else{
        mThread->Resume();
        m_checkBox_thread_pause->SetBackgroundColour( wxColour( 0, 255, 0 ));
    }
}

void MyDialog::OnOption(wxCommandEvent &event) {
    //
}

void MyDialog::OnOpenRepository( wxCommandEvent &event ) {
    auto *dialog = repDialog::getInstance( this );
    dialog->Show();
}
